#include "cgzCLua.h"
#include "cgzCTcpGateS.h"
#include "cgzCThreadPool.h"

bool cgzCLua::rungs(const cgzITask *iTask, cgzCLoopS *pnode)
{
    auto etype = pnode->getEType();
    switch (etype)
    {
    case TCPS_ACPT: // 连接成功
    {
        auto *pret = static_cast<cgzCAcptS *>(pnode);
        ocall(iTask->m_tref, "accept", {pret->m_ufd});
    }
    break;
    case TCPS_RECV: // 接收数据
    {
        auto *recv = static_cast<cgzCRecvS *>(pnode);
        auto &head = *(cgzGateHeader *)recv->m_data;
        auto *data = (const char *)(recv->m_data + sizeof(cgzGateHeader));
        ocall(iTask->m_tref, "recv", {
            recv->m_ufd, head.ufd, 
            (int)head.mid, 
            {data, (int)head.len}, 
            (long)head.cid
        });
    }
    break;
    case TCPS_DISC: // 断开连接
    {
        auto *pret = static_cast<cgzCDiscS *>(pnode);
        ocall(iTask->m_tref, "disc", {pret->m_ufd});
    }
    break;
    default:
    {
        cgz_this_error("{} type:{} not support", iTask->getName(), (int)etype);
        return false;
    }
    }
    return true;
}

static int bind(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    const char *ip = lua_tostring(L, 2);
    int port = lua_tointeger(L, 3);
    bool gate = lua_toboolean(L, 4);
    int tref = luaL_ref(L, LUA_REGISTRYINDEX);
    void *node = malloc(sizeof(cgzCTcpGateS));
    int cid = that->getId();
    auto ctcp = new (node) cgzCTcpGateS(that->m_pool, name, ip, port, cid, gate);
    ctcp->m_tref = tref;
    ctcp->tcpbind();
    lua_pushinteger(L, ctcp->getId());
    return 1;
}

static int send(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    const int gfd = lua_tointeger(L, 2);
    const int cfd = lua_tointeger(L, 3);
    const int mid = lua_tointeger(L, 4);
    size_t len = 0;
    const char *pck = lua_tolstring(L, 5, &len);
    long cid = luaL_checkinteger(L, 6);
    void *node = malloc(sizeof(cgzCSendS));
    auto psend = new (node) cgzCSendS(gfd, mid, pck, len, cfd, cid);
    that->regTask(name, psend);
    return 0;
}

static int forward_add(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    void *node = malloc(sizeof(cgzCGAddS));
    auto pCmd = new (node) cgzCGAddS();
    lua_pushnil(L);
    while (lua_next(L, -2))
    {
        int mid = lua_tointeger(L, -2);
        int tid = lua_tointeger(L, -1);
        pCmd->map[mid] = tid;
        lua_pop(L, 1);
    }
    that->regTask(name, pCmd);
    return 0;
}

static int forward_del(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    void *node = malloc(sizeof(cgzCGDelS));
    auto pCmd = new (node) cgzCGDelS();
    lua_pushnil(L);
    while (lua_next(L, -2))
    {
        int mid = lua_tointeger(L, -2);
        pCmd->set.insert(mid);
        lua_pop(L, 1);
    }
    that->regTask(name, pCmd);
    return 0;
}

static int forward_cls(lua_State *L)
{
    // 将其转换为 cgzCLua 指针
    cgzCLua *that = cgzCLua::getThat(L);
    const char *name = lua_tostring(L, 1);
    void *node = malloc(sizeof(cgzCGClrS));
    auto pCmd = new (node) cgzCGClrS();
    that->regTask(name, pCmd);
    return 0;
}

int cgzCLua::luaopen_tcpGateS(lua_State *L)
{
    static const luaL_Reg otherlib[] = {
        {"bind", bind},
        {"send", send},
        {"forward_add", forward_add},
        {"forward_del", forward_del},
        {"forward_cls", forward_cls},
        {NULL, NULL}};

    luaL_newlib(L, otherlib);
    return 1;
}